<script setup>
import { ref, reactive, watch, onMounted, h, nextTick } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus';
import { useIuserInfoStore } from '@T2/store/users.ts';
import { roleApi as MainApi, roleById as MainById, companyByIdItems } from '@T2/service/api.ts';
import { buildTree, deepCopy, getUsedMenus } from '@T2/utils/utils.ts';

const iuserInfoStore = useIuserInfoStore();
const { company_roles, created_company, info, getHandleRight } = iuserInfoStore;
const isCoSuper = created_company === info.company;
const RIGHT = getHandleRight(['295', '296', '297', '298']);

onMounted(() => {
  GetMainTable();
  getAllMenus();
});
const Rt = reactive({
  menus: {},
});
const getAllMenus = () => {
  Rt.menus = {};
  companyByIdItems({
    method: 'get',
    id: info.company,
    params: {},
  }).then(res => {
    let enlarges = [], asides = [], pmds = [];
    const CoMenus = getUsedMenus(res?.company?.children || []);
    CoMenus.forEach(item => {
      if (item.type1 === 'PMD') {
        pmds.push(item);
      } else if (item.type === 'PC-aside') {
        asides.push(item);
      } else if (item.type === 'PC-enlarge') {
        enlarges.push(item);
      }
    });
    Rt.menus = { asides, enlarges, pmds };
  });
}

const MainTable = reactive({
  data: [],
  tree: [],
});
const Filter = reactive({
  page: 1,
  pagesize: 20,
  ordering: '-create_time',
  search: '',
});
watch(() => ({...Filter}), (nv, ov) => {
  if (nv.page === 1 || nv.page !== ov.page) {
    GetMainTable();
  } else {
    Filter.page = 1;
  }
});
const GetMainTable = () => {
  MainApi({
    method: 'get',
    params: {
      ...Filter,
      project__isnull: true,
    }
  }).then(res => {
    MainTable.data = res?.results || [];
    
    let arrs = buildTree(res.results || [], 'parent');
    arrs.forEach(item => item.parent = 0);
    MainTable.tree = [ { id: 0, name: '超级管理员', permission: '超级管理员拥有所有权限', parent: null, children: arrs } ];
    getSubtreesByIds(MainTable.tree);
  });
}
const getSubtreesByIds = (tree) => {
  const setNodes = (nodes) => {
    const activeNode = (node) => {
      node.editActive = true; //右侧menus组件也使用了该值
      node.addActive = true;
      node?.children.forEach(child => activeNode(child));
    }
    for (let node of nodes) {
      /* 激活能添加下级的节点 */
      node.addActive = true;
      /* 激活能新增编辑删除的节点 */
      node?.children.forEach(child => activeNode(child));
    }
  }
  if (isCoSuper) {
    setNodes(tree);
    return;
  }
  
  /* 返回树状结构中给定ID数组 A 包含的ID及其以下的所有节点 */
  const company_roles_ids = company_roles.map(item => item.id);
  const traverse = (nodes) => {
    let result = [];
    for (let node of nodes) {
      if (company_roles_ids.includes(node.id)) {
        result.push(node);
      } else if (node.children) {
        const childResult = traverse(node.children);
        result.push(...childResult);
      }
    }
    return result;
  }
  if (company_roles_ids.length) {
    const arrs = traverse(tree);
    setNodes(arrs);
  }
  return;
}

/* 新增编辑 */
const MainPopup = reactive({
  visible: false,
  type: '新增',
});
const MainForm = reactive({
  model: {},
});
const MainFormRef = ref(null);
const handleMainAdd = (isAble = false, row) => {
  if (!isAble) {
    return;
  }
  MainPopup.visible = true;
  MainPopup.type = '新增';
  MainForm.model = {
    parent: row?.id || null,
  };
  nextTick(() => {
    MainFormRef.value.clearValidate();
  });
}
const handleMainEdit = (isAble = false, row) => {
  if (!isAble) {
    return;
  }
  MainPopup.visible = true;
  MainPopup.type = '编辑';
  MainForm.model = {
    id: row.id,
    name: row.name,
    permission: row.permission,
  };
  nextTick(() => {
    MainFormRef.value.clearValidate();
  });
}

const handleMainSubmit = () => {
  MainFormRef.value.validate((valid) => {
    if (valid) {
      MainPopup.visible = false;
      if (MainPopup.type === '新增') {
        AddMain();
      } else if (MainPopup.type === '编辑') {
        EditMain();
      }
    }
  });
}
const AddMain = () => {
  MainApi({
    method: 'post',
    data: {
      ...MainForm.model,
      company: info.company,
    }
  }).then(res => {
    ElMessage.success('新增成功');
    GetMainTable();
  });
}
const EditMain = () => {
  MainById({
    method: 'patch',
    id: MainForm.model.id,
    data: {
      ...MainForm.model,
    }
  }).then(res => {
    ElMessage.success('编辑成功');
    GetMainTable();
  });
}
const handleMainDelete = (isAble = false, row) => {
  if (!isAble) {
    return;
  }
  if (row.children?.length) {
    ElMessage.error('请先删除下级角色');
    return;
  }
  ElMessageBox.confirm('', {
    message: h('div', null,[
      h('p',{ style:'font-size:16px;color: #4C4C4C;font-weight:500;'}, `您是否要删除 ${ row.name }？`),
    ]),
    type: 'warning',
    confirmButtonText: '确认',
  }).then(() => {
    MainById({
      method: 'delete',
      id: row.id,
    }).then(res => {
      ElMessage.success('删除成功');
      GetMainTable();
    });
  }).catch(() => {
    ElMessage.info('已取消');
  });
}

/* 菜单分配 */
const menusPopup = reactive({
  visible: false,
  roleID: null,
  tables: [],
  functions: [],
  parentRole: null,
});
const handleMenus = (row) => {
  menusPopup.visible = true;
  const menus = deepCopy(Rt.menus);
  menusPopup.parentRole = MainTable.data.find(i => i.id === row.parent);
  const parentRoleMenus = menusPopup.parentRole?.menus || [];
  const parentRoleFunctions = menusPopup.parentRole?.functions || [];
  
  /* 初始化 */
  menusPopup.roleID = row.id;
  menusPopup.tables = [];
  menusPopup.functions = [];
  let newMenus = {};
  if (row.parent === 0) {
    /* 上级角色是超级管理员 */
    newMenus = menus;
  } else if (row.parent) {
    /* 上级角色存在但不是超级管理员 */
    const pruneTree = (node) => {
      const leaf = node.children?.length ? false : true;
      const children = node.children?.map(pruneTree).filter(child => child !== null) || [];
      if (children?.length) {
        /* 非叶子节点则返回过滤后的node */
        return { ...node, children };
      }
      if (leaf && node.menu && parentRoleMenus.includes(node.menu)) {
        /* 叶子节点则返回过滤后的node */
        /* 剔除上级角色不包含的菜单以及不包含的功能权限 */
        node.functions = node.functions?.filter(item => parentRoleFunctions.includes(item.id));
        return { ...node, children };
      }
      return null;
    }
    
    Object.keys(menus).forEach(key => {
      newMenus[key] = menus[key].map(pruneTree).filter((node) => node !== null) || [];
    });
  }
  if (newMenus.asides?.length) {
    menusPopup.tables.push({ alias: 'PC端-管理系统', id: 'aside', children: newMenus.asides });
  }
  if (newMenus.enlarges?.length) {
    menusPopup.tables.push({ alias: 'PC端-大屏', id: 'enlarge', children: newMenus.enlarges });
  }
  if (newMenus.pmds?.length) {
    menusPopup.tables.push({ alias: '移动端', id: 'mobile', children: newMenus.pmds });
  }
  setTimeout(() => {
    recursionSetDefaultChecked(menusPopup.tables, row.menus, row.functions);
  }, 100);
}
const treeRef = ref(null);
const recursionSetDefaultChecked = (nodes, menus, functions) => {
  for (const node of nodes) {
    if (node.children?.length > 0) {
      recursionSetDefaultChecked(node.children, menus, functions)
    } else if (node.menu && menus?.includes(node.menu)) {
      treeRef.value.setChecked(node.id, true, false);
      const arrs = node.functions?.filter(item => functions?.includes(item.id))?.map(item => item.id) || [];
      menusPopup.functions = menusPopup.functions.concat(arrs);
    }
  }
}
const handleCheck = (data, checkedArrs) => {
  const isSelected = checkedArrs.checkedKeys.some(item => item === data.id);
  const selFncs = extractCodes(data);
  if (isSelected) {
    menusPopup.functions = [...new Set([...menusPopup.functions, ...selFncs])];
  } else {
    menusPopup.functions = menusPopup.functions.filter(item => !selFncs.includes(item));
  }
}
/* 递归获取当前选择节点及一下children的所有功能点 */
const extractCodes = (tree) => {
  let ids = [];
  const traverse = (node) => {
    node.functions?.forEach(func => {
      if (func.id) {
        ids.push(func.id);
      }
    });
    node.children?.forEach(child => traverse(child));
  }
  traverse(tree);
  return ids;
}
const handleMenusSubmit = () => {
  menusPopup.visible = false;
  const menuNodes = treeRef.value.getCheckedNodes();
  const uniqueMenus = [...new Set(menuNodes.map(item => item.menu))].filter(menu => menu !== undefined && menu !== null);
  MainById({
    method: 'patch',
    id: menusPopup.roleID,
    data: {
      functions: menusPopup.functions,
      menus: uniqueMenus,
    }
  }).then(res => {
    ElMessage.success('操作成功！');
    GetMainTable();
  });
}
</script>

<template>
  <div class="view flex">
    <div class="role-box flex-column mainCard">
      <el-form label-width="100px" class="flex t_form">
        <el-form-item label="搜索：">
          <el-input v-model="Filter.search" clearable></el-input>
        </el-form-item>
      </el-form>
      <el-table :data="MainTable.tree" scrollbar-always-on row-key="id" default-expand-all>
        <el-table-column :label="`&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;角色名称`" prop="name" min-width="200px" fixed="left"></el-table-column>
        <el-table-column label="权限描述" prop="permission" min-width="200px" show-overflow-tooltip></el-table-column>
        <el-table-column label="操作" fixed="right" width="330px">
          <template #default="scope">
            <template v-if="scope.row.addActive">
              <el-button link type="primary" @click="handleMainAdd(RIGHT['295'], scope.row)" :disabled="!RIGHT['295']">
                添加下级
              </el-button>
            </template>
            
            <template v-if="scope.row.id && scope.row.editActive">
              <el-button link type="primary" @click="handleMenus(scope.row)">
                {{ RIGHT['298'] ? '权限分配' : '查看权限' }}
              </el-button>
              <el-button link type="primary" @click="handleMainEdit(RIGHT['296'], scope.row)" :disabled="!RIGHT['296']">
                编辑
              </el-button>
              <el-button link type="danger" @click="handleMainDelete(RIGHT['297'], scope.row)" :disabled="!RIGHT['297']">
                删除
              </el-button>
            </template>
          </template>
        </el-table-column>
      </el-table>
    </div>
  </div>
  
  <!-- 新增编辑 -->
  <el-dialog width="400px" :title="MainPopup.type + '角色'" v-model="MainPopup.visible">
    <el-form
      ref="MainFormRef"
      :model="MainForm.model"
      label-width="100px"
    >
      <el-form-item prop="name" label="名称：" :rules="[{required: true, message: '不能为空', trigger: 'blur'},]">
        <el-input v-model="MainForm.model.name"></el-input>
      </el-form-item>
      <el-form-item prop="permission" label="权限描述：">
        <el-input v-model="MainForm.model.permission"></el-input>
      </el-form-item>
    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="MainPopup.visible = false">取 消</el-button>
        <el-button type="primary" @click="handleMainSubmit()">确 定</el-button>
      </span>
    </template>
  </el-dialog>
  
  <!-- 菜单分配 -->
  <div>
    <el-drawer class="popup-menus" v-model="menusPopup.visible" size="1130">
      <template #header>
        <div class="title-name">权限分配</div>
      </template>
      <template #default>
        <div class="content-box">
          <!-- <div class="menu-title flex">
            <span>菜单权限</span>
            <span>操作权限</span>
          </div> -->
          <div class="scroller-aside scroll">
            <el-tree
              ref="treeRef"
              :data="menusPopup.tables"
              :props="{label: 'alias'}"
              show-checkbox
              accordion
              node-key="id"
              :default-expand-all="true"
              @check="handleCheck"
            >
              <template #default="{ node, data }">
                <span class="el-tree-node__label">{{ node.label }}</span>
                <div class="functions-list" v-if="data.menu && data.functions?.length">
                  <el-checkbox-group v-model="menusPopup.functions">
                    <el-checkbox v-for="item in data.functions" :label="item.name" :value="item.id" :key="item.id"/>
                  </el-checkbox-group>
                </div>
              </template>
            </el-tree>
          </div>
        </div>
      </template>
      <template #footer>
        <div style="flex: auto">
          <template v-if="RIGHT['298']">
            <el-button @click="menusPopup.visible = false">取 消</el-button>
            <el-button type="primary" @click="handleMenusSubmit()">确 定</el-button>
          </template>
          <template v-else>
            <el-button type="primary" @click="menusPopup.visible = false">关 闭</el-button>
          </template>
        </div>
      </template>
    </el-drawer>
  </div>
</template>

<style lang="scss" scoped>
@use '@T2/styles/normal.scss';
.view {
  width: 100%;
  height: 100%;
}
.role-box {
  flex: 1;
  overflow: hidden;
  position: relative;
}
.menu-title {
  margin-top: 20px;
  span {
    background-color: #F4F6FA;
    border: 1px solid #ebebeb;
    border-bottom: none;
    padding: 10px;
  }
  span:nth-child(1) {
    width: 40%;
    border-right: none;
  }
  span:nth-child(2) {
    border-left: none;
    width: 60%;
  }
}
.scroll {
  flex: 1;
  overflow-y: auto;
}
</style>
<style scoped>
:deep(.cell) {
  display: flex;
  align-items: center;
}

:deep(.popup-menus .el-drawer__header) {
  height: 60px;
  padding-bottom: 10px;
  margin-bottom: 0;
  border-bottom: 1px solid #EDEFF3;
}
:deep(.popup-menus .el-drawer__header .title-name) {
  font-weight: 500;
  font-size: 20px;
  color: #252525;
}

:deep(.el-tree .el-tree-node__content) {
  height: 50px;
  border-bottom: 1px solid #ebebeb;
}
:deep(.el-tree .el-tree-node__expand-icon) {
  margin: 0 10px 0 20px;
}
:deep(.el-tree .functions-list) {
  position: absolute;
  left: 40%;
  width: 60%;
}
</style>